﻿//#define MASTER_MODE     //定义程序类型，注释该行后就是从机模式程序
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;  
using System.Linq;
using System.Diagnostics;
using System.Text;
using System.IO;
using USB2XXX;

namespace USB2XXX_SENT_Test
{
    class Program
    {
        static void Main(string[] args)
        {
            USB_DEVICE.DEVICE_INFO DevInfo = new USB_DEVICE.DEVICE_INFO();
            Int32[] DevHandles = new Int32[20];
            Int32 DevHandle = 0;
            Byte Channel = 0;//0-对应LIN1，1-对应LIN2
            Byte state;
            Int32 DevNum, ret;
            string dllFilePath = "USB2XXX.dll";
            if (!File.Exists(dllFilePath))
            {
                Console.WriteLine("请先将USB2XXX.dll和libusb-1.0.dll文件复制到exe程序文件输出目录下!");
                Console.WriteLine("dll文件在‘usb2can_lin_pwm_example/sdk/libs/windows’目录下！");
                Console.WriteLine("程序配置为32位就复制‘x86_32’目录下文件，程序配置为64位就复制‘x86_64’目录下文件！");
                return;
            }
            //扫描查找设备，并将每个设备的唯一设备号存放到数组中，后面的函数需要用到
            DevNum = USB_DEVICE.USB_ScanDevice(DevHandles);
            if (DevNum <= 0)
            {
                Console.WriteLine("No device connected!");
                return;
            }
            else
            {
                Console.WriteLine("Have {0} device connected!", DevNum);
            }
            DevHandle = DevHandles[0];//获取第一个设备的设备号
            //打开设备，必须调用
            state = USB_DEVICE.USB_OpenDevice(DevHandle);
            if (state==0)
            {
                Console.WriteLine("Open device error!");
                return;
            }
            else
            {
                Console.WriteLine("Open device success!");
            }
            //获取固件信息，可以不调用
            StringBuilder FuncStr = new StringBuilder(256);
            state = USB_DEVICE.DEV_GetDeviceInfo(DevHandle, ref DevInfo, FuncStr);
            if (state==0)
            {
                Console.WriteLine("Get device infomation error!");
                return;
            }
            else
            {
                Console.WriteLine("Firmware Info:");
                Console.WriteLine("    Name:" + Encoding.Default.GetString(DevInfo.FirmwareName));
                Console.WriteLine("    Build Date:" + Encoding.Default.GetString(DevInfo.BuildDate));
                Console.WriteLine("    Firmware Version:v{0}.{1}.{2}", (DevInfo.FirmwareVersion >> 24) & 0xFF, (DevInfo.FirmwareVersion >> 16) & 0xFF, DevInfo.FirmwareVersion & 0xFFFF);
                Console.WriteLine("    Hardware Version:v{0}.{1}.{2}", (DevInfo.HardwareVersion >> 24) & 0xFF, (DevInfo.HardwareVersion >> 16) & 0xFF, DevInfo.HardwareVersion & 0xFFFF);
                Console.WriteLine("    Functions:" + DevInfo.Functions.ToString("X8"));
                Console.WriteLine("    Functions String:" + FuncStr);
            }
            //初始化配置SENT
            USB2SENT.SENT_CONFIG SentConfig;
            SentConfig.TicksTimeUs = 3;
            SentConfig.LowTicks = 5;
#if MASTER_MODE
            SentConfig.MasterMode = USB2SENT.SENT_MASTER;
#else
            SentConfig.MasterMode = USB2SENT.SENT_SLAVE;
#endif
            SentConfig.NibbleNum = 0;
            SentConfig.PausePulseTicks = 1;
            SentConfig.IdleLevel = 1;
            ret = USB2SENT.SENT_Init(DevHandles[0], Channel, ref SentConfig);
            if (ret != USB2SENT.SENT_SUCCESS) {
                Console.WriteLine("Config SENT failed!");
                return;
            }
            else {
                Console.WriteLine("Config SENT Success!");
            }
#if MASTER_MODE
            //Enhanced serial message format with 12-bit data field and 8-bit message id
            //Enhanced serial message format with 16-bit data field and 4-bit message id
            USB2SENT.SENT_MSG[] SlowSentMsg = new USB2SENT.SENT_MSG[5];
            for (int i = 0;i < 5;i++) {
                UInt16 data = (UInt16)(0x1030+((i<<8)|i));
                SlowSentMsg[i].Timestamp = 5;
                SlowSentMsg[i].TimestampHigh = 1;
                SlowSentMsg[i].MsgType = 4;
                SlowSentMsg[i].Status = 3<<4;
                SlowSentMsg[i].Data[0] = (Byte)(0x70+i);
                SlowSentMsg[i].Data[1] = (Byte)(data>>8);
                SlowSentMsg[i].Data[2] = (Byte)(data&0xFF);
            }

            ret = USB2SENT.SENT_StartSlowMsgTable(DevHandles[0], Channel, SlowSentMsg, 5, 0xFFFFFFFF);
            Console.WriteLine("SENT_StartSlowFastMsgTable ret=%d", ret);

            USB2SENT.SENT_MSG[] SentMsg = new USB2SENT.SENT_MSG[18];
            for (int i = 0;i < SentMsg.Length;i++) {
                SentMsg[i].Timestamp = 20;
                SentMsg[i].TimestampHigh = 1;
                SentMsg[i].MsgType = 1;
                SentMsg[i].Status = 6 << 4;
                SentMsg[i].Data[0] = (Byte)(i&0xF);
                SentMsg[i].Data[1] = (Byte)(i & 0xF);
                SentMsg[i].Data[2] = (Byte)(i & 0xF);
                SentMsg[i].Data[3] = (Byte)(i & 0xF);
                SentMsg[i].Data[4] = (Byte)(i & 0xF);
                SentMsg[i].Data[5] = (Byte)(i & 0xF);
            }
            ret = USB2SENT.SENT_StartFastMsgTable(DevHandles[0], Channel, SentMsg, 18, 0xFFFFFFFF);
            if (ret != USB2SENT.SENT_SUCCESS) {
                Console.WriteLine("Send SENT failed!");
                return;
            }
            else {
                Console.WriteLine("Send SENT Success!");
            }
            //接收发送出去的数据
            for (int t = 0;t < 10;t++) {
                USB2SENT.SENT_MSG[] msg = new USB2SENT.SENT_MSG[1000];
                //申请存储数据缓冲区
                IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2SENT.SENT_MSG)) * msg.Length);
                ret = USB2SENT.SENT_GetMsg(DevHandles[0], Channel, pt);
                for (int i = 0;i < ret;i++) {
                    msg[i] = (USB2SENT.SENT_MSG)Marshal.PtrToStructure((IntPtr)(pt + i * Marshal.SizeOf(typeof(USB2SENT.SENT_MSG))), typeof(USB2SENT.SENT_MSG));
                    Console.Write("[%02d:%02d:%03d][%02X]:", (msg[i].Timestamp / 600000) % 24, (msg[i].Timestamp / 10000) % 60, (msg[i].Timestamp / 10) % 1000, msg[i].MsgType);
                    if ((msg[i].MsgType&0xF) == 1) {
                        Console.Write(" %02X", msg[i].Status);
                        for (int j = 0;j < ((msg[i].Status >> 4) & 0xF);j++) {
                            Console.Write(" %02X", msg[i].Data[j]);
                        }
                        Console.Write(" %02X\n", msg[i].crc);
                    }
                    else if ((msg[i].MsgType & 0xF) == 2) {
                        Console.Write(" [%d]ID=%02X DATA=%02X CRC=%02X\n", msg[i].MsgType, msg[i].Data[0], msg[i].Data[1], msg[i].crc);
                    }
                    else if ((msg[i].MsgType & 0xF) == 3) {
                        Console.Write(" [%d]ID=%02X DATA=%04X CRC=%02X\n", msg[i].MsgType, msg[i].Data[0], ((msg[i].Data[1] & 0xF) << 8) | msg[i].Data[2], msg[i].crc);
                    }
                    else if ((msg[i].MsgType & 0xF) == 4) {
                        Console.Write(" [%d]ID=%02X DATA=%04X CRC=%02X\n", msg[i].MsgType, msg[i].Data[0], (msg[i].Data[1] << 8) | msg[i].Data[2], msg[i].crc);
                    }
                }
                //释放申请的数据缓冲区
                Marshal.FreeHGlobal(pt);
                System.Threading.Thread.Sleep(20);
            }
            USB2SENT.SENT_StopFastMsgTable(DevHandles[0], Channel);
#else
            //接收收到的数据
            for (int t = 0;t < 10;t++) {
                USB2SENT.SENT_MSG[] msg = new USB2SENT.SENT_MSG[1000];
                //申请存储数据缓冲区
                IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2SENT.SENT_MSG)) * msg.Length);
                ret = USB2SENT.SENT_GetMsg(DevHandles[0], Channel, pt);
                for (int i = 0;i < ret;i++) {
                    msg[i] = (USB2SENT.SENT_MSG)Marshal.PtrToStructure((IntPtr)(pt + i * Marshal.SizeOf(typeof(USB2SENT.SENT_MSG))), typeof(USB2SENT.SENT_MSG));
                    Console.Write("[%02d:%02d:%03d][%02X]:", (msg[i].Timestamp / 600000) % 24, (msg[i].Timestamp / 10000) % 60, (msg[i].Timestamp / 10) % 1000, msg[i].MsgType);
                    if ((msg[i].MsgType&0xF) == 1) {
                        Console.Write(" %02X", msg[i].Status);
                        for (int j = 0;j < ((msg[i].Status >> 4) & 0xF);j++) {
                            Console.Write(" %02X", msg[i].Data[j]);
                        }
                        Console.Write(" %02X\n", msg[i].crc);
                    }
                    else if ((msg[i].MsgType & 0xF) == 2) {
                        Console.Write(" [%d]ID=%02X DATA=%02X CRC=%02X\n", msg[i].MsgType, msg[i].Data[0], msg[i].Data[1], msg[i].crc);
                    }
                    else if ((msg[i].MsgType & 0xF) == 3) {
                        Console.Write(" [%d]ID=%02X DATA=%04X CRC=%02X\n", msg[i].MsgType, msg[i].Data[0], ((msg[i].Data[1] & 0xF) << 8) | msg[i].Data[2], msg[i].crc);
                    }
                    else if ((msg[i].MsgType & 0xF) == 4) {
                        Console.Write(" [%d]ID=%02X DATA=%04X CRC=%02X\n", msg[i].MsgType, msg[i].Data[0], (msg[i].Data[1] << 8) | msg[i].Data[2], msg[i].crc);
                    }
                }
                //释放申请的数据缓冲区
                Marshal.FreeHGlobal(pt);
                System.Threading.Thread.Sleep(20);
            }
#endif
	        return;
        }
    }
}
